package com.net.xpay.core.utils;


import com.google.common.base.Preconditions;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cglib.beans.BeanCopier;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

/**
 * @author net
 * 对象属性拷贝工具类
 */
@Slf4j
public class BeanCopierUtil {
    private static final Logger LOGGER = LoggerFactory.getLogger(BeanCopierUtil.class);

    public static <S, T> void copy(S source, T target) {
        Preconditions.checkArgument(source != null && target != null);
        Class sourceCls = source.getClass();
        Class targetCls = target.getClass();

        BeanCopier beanCopier = BeanCopier.create(sourceCls, targetCls, false);

        beanCopier.copy(source, target, null);
    }


    public static <S, T> List<T> batchCopy(Class<S> sourceCls, Class<T> targetCls, List<S> sources) {
        Preconditions.checkArgument(sourceCls != null && targetCls != null);
        if (CollectionUtils.isEmpty(sources)) {
            return new ArrayList<>();
        }

        BeanCopier beanCopier = BeanCopier.create(sourceCls, targetCls, false);
        List<T> targets = new ArrayList<>();
        for (S source : sources) {
            T target;
            try {
                target = targetCls.newInstance();
            } catch (Exception e) {
                LOGGER.error("batchCopy target newInstance error|sourceCls={}|targetCls={}", sourceCls, targetCls);
                throw new RuntimeException("batchCopy target newInstance error");
            }

            beanCopier.copy(source, target, null);

            targets.add(target);
        }
        return targets;
    }


    /**
     * 根据指定的注解拷贝
     */
    public static <S, T> void copyByAnnotation(S source, T target, Class<? extends Annotation> annotationClass) {
        Field[] fields = target.getClass().getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            if (!field.isAnnotationPresent(annotationClass)) {
                continue;
            }

            try {
                if (field.get(source) == null) {
                    continue;
                }
                field.set(target, field.get(source));
            } catch (IllegalAccessException e) {
                log.error("copyByAnnotation error", e);
            }
        }
    }
}
